package basicGramer

import (
	"fmt"
	"time"
)

// 记录一些并发线程的使用

func init() {
	fmt.Println("\n\n============这里是basicGramer/Thread.go类中的init()加载事件")
	goRouTime()   // 协程的使用
	channelTest() // 信道的定义、 只读信道和只写信道
}

//

// 定义一个只读信道
type Receiver = <-chan int

// 定义一个只写信道
type Sender = chan<- int

// 信道的使用
func channelTest() {
	// 定义一个int类型的信道
	pipline := make(chan int, 10) // 定义一个10长度的信道,  10是可以省略的，如果是1的话，可以利用锁机制来使用
	// pipline :=make(chan int) 这样就是一个同步的信道传输
	fmt.Printf("信道可以缓冲%d个数据\n", cap(pipline))
	pipline <- 3
	fmt.Printf("信道中当前有%d个数据\n", len(pipline))

	// FIXME 双向通道和单向通道
	chanSendAndReceive()
	forRangeChan()
	chanCopy()
}

/*
   cloneCopy
   值类型 String Array int Struct Float Bool
   引用类型 Slice Map对象
	FIXME 重点： 值类型的copy后，新的对象修改是不印象旧数据的   即：深拷贝
*/
func chanCopy() {
	// 值类型的拷贝
	aArray := [3]int{1, 2, 3} // 定义一个数组，如果不指定数值大小 就是slice区块  是引用类型了都
	bArray := aArray
	aArray[0] = 99
	fmt.Println("aArray的数组内容是：", aArray)
	fmt.Println("bArray的数组内容是：", bArray)
	/*结果是：aArray的数组内容是： [99 2 3]
	bArray的数组内容是： [1 2 3]*/

	// 引用类型的拷贝
	aSlice := []int{1, 2, 3}
	bSlice := aSlice
	aSlice[0] = 88
	fmt.Println("aSlice的数组内容是：", aSlice)
	fmt.Println("bSlice的数组内容是：", bSlice)
}

// 遍历信道数据
func forRangeChan() {
	mychan := make(chan int, 10)
	go makeChanMessage(mychan)
	for k := range mychan {
		fmt.Printf("接收到的信道数据是：%d\n", k)
	}
}

// 制造信道传输的数据
func makeChanMessage(mychan chan int) {
	n := cap(mychan)
	x, y := 1, 1
	for i := 0; i < n; i++ {
		mychan <- x
		x, y = y, x+y
	}
	close(mychan)
}

func chanSendAndReceive() {
	line := make(chan int, 10)
	go func() {
		var send Sender = line
		fmt.Printf("开始发送数据%d\n", 100)
		send <- 100
	}()
	go func() {
		var receive Receiver = line
		data := <-receive
		fmt.Printf("开始接受数据%d\n", data)
	}()

	time.Sleep(time.Second)
}

// 循环打印两个进程的数据
func goRouTime() {
	go myGo("协程1号")
	go myGo("协程2号")
	time.Sleep(time.Second)
}

// 打印当前协程的名称
func myGo(name string) {
	for i := 0; i < 5; i++ {
		fmt.Printf(" 第%d次 In goroutine %s\n", i, name)
		// 等待着 可	以看到变化
		time.Sleep(10 * time.Millisecond)
	}
}
